﻿using LightCAD.MathLib;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static LightCAD.MathLib.Constants;

namespace LightCAD.Three
{

    public class WebGLCubeUVMaps : WebGLCubeMaps
    {
        private JsObj<Texture, WebGLRenderTarget> cubeUVmaps;
        private PMREMGenerator pmremGenerator = null;
        private WebGLRenderer renderer;
        public WebGLCubeUVMaps(WebGLRenderer renderer) : base(renderer)
        {
            this.cubeUVmaps = new JsObj<Texture, WebGLRenderTarget>();
            this.pmremGenerator = null;
            this.renderer = renderer;
        }
        public override Texture get(Texture texture)
        {
            if (texture != null)
            {

                var mapping = texture.mapping;

                var isEquirectMap = (mapping == EquirectangularReflectionMapping || mapping == EquirectangularRefractionMapping);
                var isCubeMap = (mapping == CubeReflectionMapping || mapping == CubeRefractionMapping);

                // equirect/cube map to cubeUV conversion

                if (isEquirectMap || isCubeMap)
                {
                    if (texture.isRenderTargetTexture && texture.needsPMREMUpdate)
                    {

                        texture.needsPMREMUpdate = false;

                        var renderTarget = cubeUVmaps.get(texture);
                        if (pmremGenerator == null) pmremGenerator = new PMREMGenerator(renderer);
                        renderTarget = isEquirectMap ? pmremGenerator.fromEquirectangular(texture, renderTarget) : pmremGenerator.fromCubemap(texture as CubeTexture, renderTarget);
                        cubeUVmaps.set(texture, renderTarget);
                        return renderTarget.texture;
                    }
                    else
                    {
                        if (cubeUVmaps.has(texture))
                        {
                            return cubeUVmaps.get(texture).texture;
                        }
                        else
                        {

                            var image = texture.image;

                            if ((isEquirectMap && image != null && image.height > 0) || (isCubeMap && image != null && isCubeTextureComplete((texture as CubeTexture).images.Cast<Image>().ToListEx())))
                            {
                                if (pmremGenerator == null) pmremGenerator = new PMREMGenerator(renderer);
                                var renderTarget = isEquirectMap ? pmremGenerator.fromEquirectangular(texture) : pmremGenerator.fromCubemap(texture as CubeTexture);
                                cubeUVmaps.set(texture, renderTarget);
                                texture.addEventListener("dispose", onTextureDispose);
                                return renderTarget.texture;

                            }
                            else
                            {

                                // image not yet ready. try the conversion next frame

                                return null;

                            }

                        }

                    }

                }
            }

            return texture;

        }

        public bool isCubeTextureComplete(ListEx<Image> image)
        {

            var count = 0;
            var length = 6;

            for (var i = 0; i < length; i++)
            {

                if (image[i] != null) count++;

            }
            return count == length;

        }

        public void onTextureDispose(EventArgs e)
        {

            var texture = (Texture)e.target;

            texture.removeEventListener("dispose", onTextureDispose);

            var cubemapUV = cubeUVmaps.get(texture);

            if (cubemapUV != null)
            {

                cubeUVmaps.delete(texture);
                cubemapUV.dispose();

            }

        }

        public override void dispose()
        {

            cubeUVmaps = new JsObj<Texture, WebGLRenderTarget>();

            if (pmremGenerator != null)
            {
                pmremGenerator.dispose();
                pmremGenerator = null;
            }
        }
    }
}
